
;; a)
(define (lookup-variable-value var env)
  (define (env-loop env)
    (define (scan vars vals)
      (cond ((null? vars)
             (env-loop (enclosing-environment env)))
            ((eq? var (car vars))
             (if (eq? (car vals) '*unassigned*)
                 (error "Unassigned variable" var)
                 (car vals)))
            (else (scan (cdr vars) (cdr vals)))))
    (if (eq? env the-empty-environment)
        (error "Unbound variable" var)
        (let ((frame (first-frame env)))
          (scan (frame-variables frame)
                (frame-values frame)))))
  (env-loop env))

;; b)
(define (scan-out-defines procedure-body)
  (define (iter body res1 res2)
    (cond ((null? body)
           (cons res1 res2))
          ((definition? (car body))
           (iter (cdr body) res1 (cons (car body) res2)))
          (else
           (iter (cdr body) (cons (car body) res1) res2))))
  (let ((sepa (iter procedure-body '() '())))
    (let ((body (car sepa)) (defines (cdr sepa)))
      (if (null? defines)
          procedure-body
          (let ((define-vars (map definition-variable defines))
                (define-vals (map definition-value defines)))
            (list (make-let (map (lambda (var) (list var ''*unassigned*))
                                 define-vars)
                            (append (map (lambda (var val)
                                           (list 'set! var val))
                                         define-vars
                                         define-vals)
                                    body))))))))

;; c)
;(define (f x) (define (even? n) (if (= n 0) true (odd? (- n 1)))) (define (odd? n) (if (= n 0) false (even? (- n 1)))) (even? x))